// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

import { Utils } from "../../../CCFramework/util/Utils";
import Shader from "../../Shader";

const { ccclass, property, executeInEditMode } = cc._decorator;

@ccclass
@executeInEditMode
export default class GaussBlurShader extends Shader {
    @property(cc.EffectAsset)
    private _gaussEffect: cc.EffectAsset = null;

    @property(cc.EffectAsset)
    get gaussEffect(): cc.EffectAsset {
        return this._gaussEffect;
    }
    set gaussEffect(value: cc.EffectAsset) {
        this._gaussEffect = value;
        this.updateBlurMaterial();
        this.updateBlur();
    }


    @property
    _iteration: number = 1;

    @property({
        min: 1
    })
    get iteration() {
        return this._iteration;
    }

    set iteration(value) {
        if (value == this._iteration) return;
        this._iteration = value;
        this.updateBlur();
    }

    @property
    _downLevel: number = 1;

    @property({
        min: 1
    })
    get downLevel() {
        return this._downLevel;
    }

    set downLevel(value) {
        if (value == this._downLevel) return;
        this._downLevel = value;
        this.updateBlur();
    }

    @property
    private _textureSize: cc.Vec2 = cc.v2(512, 512);

    @property
    get textureSize(): cc.Vec2 {
        return this._textureSize;
    }
    set textureSize(value: cc.Vec2) {
        this._textureSize = value;
    }

    private _srcTex2D: cc.Texture2D = null;
    private _desTex2D: cc.Texture2D = null;
    private _vMaterial: cc.Material = null;
    private _hMaterial: cc.Material = null;
    private _originTexture: cc.Texture2D = null;
    private _originSpriteFrame: cc.SpriteFrame = null;

    protected start(): void {
        this._originSpriteFrame = (this.renderComponent as cc.Sprite).spriteFrame;
        this._originTexture = this._originSpriteFrame.getTexture();
        this._srcTex2D = new cc.Texture2D();
        this._desTex2D = new cc.Texture2D();
        this.updateBlurMaterial();
        this.updateBlur();
    }

    private updateBlur() {
        if (!this._gaussEffect) return;
        (this.renderComponent as cc.Sprite).spriteFrame.setTexture(this._originTexture);
        this.renderComponent['_updateMaterial']();
        Utils.renderNodeToTexture(this.node, this._srcTex2D);
        Utils.renderTextureToTexture(this._srcTex2D, this._desTex2D, [this._vMaterial, this._hMaterial], this._iteration, this._downLevel);
        (this.renderComponent as cc.Sprite).spriteFrame.setTexture(this._desTex2D);
        this.renderComponent['_updateMaterial']();
    }

    private updateBlurMaterial() {
        if (!this._gaussEffect) return;
        this._vMaterial = cc.Material.create(this.gaussEffect, 0);
        this._hMaterial = cc.Material.create(this.gaussEffect, 1);

        this._vMaterial.setProperty("u_texSize", this._textureSize);
        this._hMaterial.setProperty("u_texSize", this._textureSize);
    }
}
